//
//  ZPPermanentThread.m
//  ZPPermanentThreadDemo
//
//  Created by mac on 2020/3/17.
//  Copyright © 2020 com.codezp. All rights reserved.
//

#import "ZPPermanentThread.h"

#pragma mark ---------------------
#pragma mark 测试用
@interface ZPThread : NSThread

@end

@implementation ZPThread
- (void)dealloc {
    NSLog(@"%s", __func__);
}
@end

@interface ZPPermanentThread ()
/** 线程 */
@property (nonatomic, strong) ZPThread *innerThread;
@end

@implementation ZPPermanentThread

- (instancetype)init {
    if (self = [super init]) {
        [self createThread];
    }
    return self;
}

- (void)dealloc {
    NSLog(@"%s", __func__);
    [self stop];
}

#pragma mark ---------------------
#pragma mark 外部接口
- (void)run {
    if (!self.innerThread || self.innerThread.isExecuting) return;
    [self.innerThread start];
}

- (void)stop {
    if (!self.innerThread) return;
    [self performSelector:@selector(__stop) onThread:self.innerThread withObject:nil waitUntilDone:YES];
}

- (void)executeTask:(ZPPermanentThreadTask)task {
    if (!self.innerThread || !task) return;
    [self performSelector:@selector(__execute:) onThread:self.innerThread withObject:task waitUntilDone:NO];
}

- (void)executeTaskWithTarget:(id)target action:(SEL)action {
    if (!self.innerThread) return;
    [target performSelector:action onThread:self.innerThread withObject:nil waitUntilDone:NO];
}

#pragma mark ---------------------
#pragma mark 私有方法
- (void)createThread {
    self.innerThread = [[ZPThread alloc] initWithBlock:^{
        // 上下文 并清零
        CFRunLoopSourceContext context = {0};
        // 创建一个源 保证Runloop不退出
        CFRunLoopSourceRef source = CFRunLoopSourceCreate(CFAllocatorGetDefault(), 0, &context);
        // 添加一个源到Runloop
        CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
        // (false)运行一次不会退出
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false);
        CFRelease(source);
    }];
    // 如果没有正在执行的任务 开启
    if (!self.innerThread.isExecuting) [self.innerThread start];
}

- (void)__stop {
    // 停止Runloop
    CFRunLoopStop(CFRunLoopGetCurrent());
    // 清空线程
    self.innerThread = nil;
}

- (void)__execute:(ZPPermanentThreadTask)task {
    task();
}

@end
